package com.example.jwtauthdemo.security;

import com.example.jwtauthdemo.util.JwtUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


import java.io.IOException;
import java.util.Enumeration;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private static final Log logger = LogFactory.getLog(JwtAuthenticationFilter.class);

    private final JwtUtil jwtUtil;
    private final UserDetailsService userDetailsService;

    public JwtAuthenticationFilter(JwtUtil jwtUtil, UserDetailsService userDetailsService) {
        this.jwtUtil = jwtUtil;
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        
        String requestURI = request.getRequestURI();
        logger.info("请求URI: " + requestURI);
        
        // 豁免登录和注册接口
        if (requestURI.equals("/api/auth/login") || requestURI.equals("/api/auth/register")) {
            logger.info("豁免JWT认证: " + requestURI);
            filterChain.doFilter(request, response);
            return;
        }
        
        // 获取所有请求头用于调试
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            logger.info("请求头: " + headerName + ": " + request.getHeader(headerName));
        }
        
        // 获取Authorization头
        final String authorizationHeader = request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        logger.info("开始处理JWT认证过滤器");
        logger.info("Authorization头: " + authorizationHeader);
        // 检查Authorization头是否有效
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
                logger.info("提取JWT令牌成功: " + jwt.substring(0, 10) + "..."); // 仅记录前10个字符
            try {
                username = jwtUtil.extractUsername(jwt);
                    
            } catch (Exception e) {
                logger.error("无法解析JWT令牌: " + e.getMessage(), e);
            }
        }

        // 如果用户名不为空且当前上下文没有认证信息
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
            logger.info("成功加载用户详情: " + userDetails.getUsername());
            
            // 验证令牌
            boolean tokenValid = jwtUtil.validateToken(jwt, userDetails);
                logger.info("令牌验证结果: " + tokenValid);
                if (tokenValid) {
                logger.info("JWT令牌验证成功，设置认证信息");
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = 
                    new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                    .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        
        logger.info("JWT认证过滤器处理完成，认证状态: " + (SecurityContextHolder.getContext().getAuthentication() != null));
        filterChain.doFilter(request, response);
    }
}